package org.xxpay.pay.channel.sufpay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.MD5Util;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.PayDigestUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.Map;

/**
 * @description: 速付支付回调处理
 */
@Service
public class SufpayPayNotifyService extends BasePayNotify {

    private static final MyLog _log = MyLog.getLog(SufpayPayNotifyService.class);
    private static final String logPrefix = "【处理"+SufpayConfig.CHANNEL_NAME+"支付回调】";

    @Override
    public String getChannelName() {
        return SufpayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {

        _log.info("====== 开始处理"+getChannelName()+"支付回调通知 ======");
        HttpServletRequest req = (HttpServletRequest) notifyData;
        JSONObject retObj = new JSONObject();

        PayOrder payOrder = verifyAliPayParams(req);
        if( payOrder == null ) { //验证参数失败
            retObj.put(PayConstant.RESPONSE_RESULT, PayConstant.RETURN_ALIPAY_VALUE_FAIL);
            return retObj;
        }

        //订单已经支付完成
        if(payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS || payOrder.getStatus() == PayConstant.PAY_STATUS_COMPLETE){
            retObj.put(PayConstant.RESPONSE_RESULT, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
            return retObj;
        }

        int updatePayOrderRows = commonService.payOrderService.updateStatus4Success(payOrder.getPayOrderId());
        if (updatePayOrderRows != 1) {
            _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
            retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
            return retObj;
        }
        _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
        payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);

        // 业务系统后端通知
        baseNotify4MchPay.doNotify(payOrder, true);

        retObj.put(PayConstant.RESPONSE_RESULT, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
        return  retObj;
    }

    /**
     * 验证通知参数
     * @return
     */
    private PayOrder verifyAliPayParams(HttpServletRequest req) {

        _log.info("{}请求参数：{}", logPrefix, getJsonParam(req));

        //验证参数是否合法
        String sysOrderNo = req.getParameter("sysOrderNo");
        String myselfOrderId = req.getParameter("mchOrderNo");
        String amount = req.getParameter("amount");
        String status = req.getParameter("status");

        _log.info("{}验证参数sysOrderNo={}, myselfOrderId={}, amount={}, status={}", logPrefix, sysOrderNo, myselfOrderId, amount, status);

        if(StringUtils.isAnyEmpty(sysOrderNo, myselfOrderId, amount, status)){
            _log.error("{}必要参数为空sysOrderNo={}, myselfOrderId={}, amount={}, status={}", logPrefix, sysOrderNo, myselfOrderId, amount, status);
            return null;
        }

        if(!"1".equals(status)) {
            _log.error("{}订单状态为失败,myselfOrderId={}", logPrefix, myselfOrderId);
            return null;
        }

        PayOrder payOrder = commonService.payOrderService.findByPayOrderId(myselfOrderId); // 根据myselfOrderId查单
        if(payOrder == null){
            _log.error("{}查单失败myselfOrderId={}", logPrefix, myselfOrderId);
            return null;
        }

        Long amountL = Long.parseLong(amount);
        if(!amountL.equals(payOrder.getAmount())){
            _log.error("{}订单金额验证失败， myselfAmount={}, amount={}", logPrefix, payOrder.getAmount(), amount);
            return null;
        }

        JSONObject reqDataJSON = new JSONObject();
        reqDataJSON.put("mchOrderNo", req.getParameter("mchOrderNo"));
        reqDataJSON.put("sysOrderNo", req.getParameter("sysOrderNo"));
        reqDataJSON.put("amount", req.getParameter("amount"));
        reqDataJSON.put("mchId", req.getParameter("mchId"));
        reqDataJSON.put("pay_type", req.getParameter("pay_type"));
        reqDataJSON.put("param", req.getParameter("param"));
        reqDataJSON.put("payOrderId", req.getParameter("payOrderId"));
        reqDataJSON.put("timeDate", req.getParameter("timeDate"));
        reqDataJSON.put("status", req.getParameter("status"));

        String sign = req.getParameter("sign");

        SufpayConfig sufpayConfig = new SufpayConfig(getPayParam(payOrder));

        String checkSign = PayDigestUtil.getSign(reqDataJSON, sufpayConfig.getKey()).toLowerCase();
        if (!checkSign.equalsIgnoreCase(sign)) {
            _log.error("{}验签失败,checkSign={},sign={}", logPrefix, checkSign, sign);
            return null;
        }

        return payOrder;
    }

    protected JSONObject getJsonParam(HttpServletRequest request) {
        String params = request.getParameter("params");
        if(StringUtils.isNotBlank(params)) {
            return JSON.parseObject(params);
        }
        // 参数Map
        Map properties = request.getParameterMap();
        // 返回值Map
        JSONObject returnObject = new JSONObject();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name;
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if(null == valueObj){
                value = "";
            }else if(valueObj instanceof String[]){
                String[] values = (String[])valueObj;
                for(int i=0;i<values.length;i++){
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length()-1);
            }else{
                value = valueObj.toString();
            }

            returnObject.put(name, value);
        }
        return returnObject;
    }

    public static void main(String[] args) {

        String s = "amount=300&mchId=699107717365&mchOrderNo=P01202004051820205320005&pay_type=aliwap&status=1&sysOrderNo=956a23c1586082039219&timeDate=1586084958&key=83107ce3dd9636a82110b65875031744";

        System.out.println(MD5Util.string2MD5(s).toLowerCase());

    }

}
